/* eslint-disable no-useless-escape */
import Prism from 'prismjs';
const blocks = '(if|else if|await|then|catch|each|html|debug)';

Prism.languages.svelte = Prism.languages.extend('markup', {
	each: {
		pattern: new RegExp(
			'{[#/]each' + '(?:(?:\\{(?:(?:\\{(?:[^{}])*\\})|(?:[^{}]))*\\})|(?:[^{}]))*}'
		),
		inside: {
			'language-javascript': [
				{
					pattern: /(as[\s\S]*)\([\s\S]*\)(?=\s*\})/,
					lookbehind: true,
					inside: Prism.languages['javascript']
				},
				{
					pattern: /(as[\s]*)[\s\S]*(?=\s*)/,
					lookbehind: true,
					inside: Prism.languages['javascript']
				},
				{
					pattern: /(#each[\s]*)[\s\S]*(?=as)/,
					lookbehind: true,
					inside: Prism.languages['javascript']
				}
			],
			keyword: /[#/]each|as/,
			punctuation: /{|}/
		}
	},
	if: {
		pattern: new RegExp(
			'{[#/]if' + '(?:(?:\\{(?:(?:\\{(?:[^{}])*\\})|(?:[^{}]))*\\})|(?:[^{}]))*}'
		),
		inside: {
			'language-javascript': [
				{
					pattern: /(as[\s\S]*)\([\s\S]*\)(?=\s*\})/,
					lookbehind: true,
					inside: Prism.languages['javascript']
				},
				{
					pattern: /(as[\s]*)[\s\S]*(?=\s*)/,
					lookbehind: true,
					inside: Prism.languages['javascript']
				},
				{
					pattern: /(#if[\s]*)[\s\S]*(?=as)/,
					lookbehind: true,
					inside: Prism.languages['javascript']
				}
			],
			keyword: /[#/]if|as/,
			punctuation: /{|}/
		}
	},
	block: {
		pattern: new RegExp(
			'{[#:/@]/s' + blocks + '(?:(?:\\{(?:(?:\\{(?:[^{}])*\\})|(?:[^{}]))*\\})|(?:[^{}]))*}'
		),
		inside: {
			punctuation: /^{|}$/,
			keyword: [new RegExp('[#:/@]' + blocks + '( )*'), /as/, /then/],
			'language-javascript': {
				pattern: /[\s\S]*/,
				inside: Prism.languages['javascript']
			}
		}
	},
	tag: {
		pattern:
			/<\/?(?!\d)[^\s>\/=$<%]+(?:\s(?:\s*[^\s>\/=]+(?:\s*=\s*(?:(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?:"[^"]*"|'[^']*'|{[\s\S]+?}(?=[\s/>])))|(?=[\s/>])))+)?\s*\/?>/i,
		greedy: true,
		inside: {
			tag: {
				pattern: /^<\/?[^\s>\/]+/i,
				inside: {
					punctuation: /^<\/?/,
					namespace: /^[^\s>\/:]+:/
				}
			},
			'language-javascript': {
				pattern: /\{(?:(?:\{(?:(?:\{(?:[^{}])*\})|(?:[^{}]))*\})|(?:[^{}]))*\}/,
				inside: Prism.languages['javascript']
			},
			'attr-value': {
				pattern: /=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+)/i,
				inside: {
					punctuation: [
						/^=/,
						{
							pattern: /^(\s*)["']|["']$/,
							lookbehind: true
						}
					],
					'language-javascript': {
						pattern: /{[\s\S]+}/,
						inside: Prism.languages['javascript']
					}
				}
			},
			punctuation: /\/?>/,
			'attr-name': {
				pattern: /[^\s>\/]+/,
				inside: {
					namespace: /^[^\s>\/:]+:/
				}
			}
		}
	},
	'language-javascript': {
		pattern: /\{(?:(?:\{(?:(?:\{(?:[^{}])*\})|(?:[^{}]))*\})|(?:[^{}]))*\}/,
		lookbehind: true,
		inside: Prism.languages['javascript']
	}
});

Prism.languages.svelte['tag'].inside['attr-value'].inside['entity'] =
	Prism.languages.svelte['entity'];

Prism.hooks.add('wrap', (env) => {
	if (env.type === 'entity') {
		env.attributes['title'] = env.content.replace(/&amp;/, '&');
	}
});

Object.defineProperty(Prism.languages.svelte.tag, 'addInlined', {
	value: function addInlined(tagName, lang) {
		const includedCdataInside = {};
		includedCdataInside['language-' + lang] = {
			pattern: /(^<!\[CDATA\[)[\s\S]+?(?=\]\]>$)/i,
			lookbehind: true,
			inside: Prism.languages[lang]
		};
		includedCdataInside['cdata'] = /^<!\[CDATA\[|\]\]>$/i;

		const inside = {
			'included-cdata': {
				pattern: /<!\[CDATA\[[\s\S]*?\]\]>/i,
				inside: includedCdataInside
			}
		};
		inside['language-' + lang] = {
			pattern: /[\s\S]+/,
			inside: Prism.languages[lang]
		};

		const def = {};
		def[tagName] = {
			pattern: RegExp(
				/(<__[\s\S]*?>)(?:<!\[CDATA\[[\s\S]*?\]\]>\s*|[\s\S])*?(?=<\/__>)/.source.replace(
					/__/g,
					tagName
				),
				'i'
			),
			lookbehind: true,
			greedy: true,
			inside
		};

		Prism.languages.insertBefore('svelte', 'cdata', def);
	}
});

Prism.languages.svelte.tag.addInlined('style', 'css');
Prism.languages.svelte.tag.addInlined('script', 'javascript');
